/**  
 * @Title:  hjg1.java   
 * @Package com.wkr.jdbc.teacher   
 * @Description:    TODO(用一句话描述该文件做什么)   
 * @author: WuKangrong     
 * @date:   2018年8月24日 下午7:24:54   
 * @version V
 * @JDKversion:1.8.0
 * @Copyright: 2018  
*/
package com.wkr.jdbc.teacher;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

import org.apache.commons.beanutils.BeanUtils;

/**   
 * @ClassName:  hjg1   
 * @Description:TODO(这里用一句话描述这个类的作用)   
 * @author: WuKangrong 
 * @date:   2018年8月24日 下午7:24:54     
 * @Copyright: 2018 
 */
public class DBProvider {
	
	
	public Connection getConn() {
		// 返回类型
		Connection conn = null;
		try {
			// (1) 注册加载数据库驱动
			// 数据库驱动主类的包路径名，使用反射加载
			String strDirverName = "oracle.jdbc.OracleDriver";
			Class.forName(strDirverName);
			// (2) 获取数据库连接对象
			// 数据库连接各个属性
			// url连接串
			// 解析连接串：@前面固定写法；@后面是数据库服务器的ip地址或主机名；
			// 1521 数据库服务器监听的端口号；orcl：数据库名数据实例名
			String strUrl = "jdbc:oracle:thin:@localhost:1521:orcl";
			// 用户名
			String strUserName = "hr";
			// 密码
			String strUserPsw = "hr";
			// 从驱动管理类中获取指定参数的数据库连接对象
			conn = DriverManager.getConnection(strUrl, strUserName, strUserPsw);
		} catch (Exception e) {
			// 数据库创建连接异常
			System.out.println("数据库创建连接异常:" + e.getMessage());
			e.printStackTrace();
		}
		// 返回值
		return conn;
	}
	
	public static  <T> List<T> convertResultSet2BeanList(ResultSet rs, Class<T> clazz) {
		// 返回值
		List<T> lst = new ArrayList<>();
		if (rs != null) {
			try {
				// 因为已经遍历过一次结果，所有再次遍历之前，需要将光标移动到最前位置（第一行之前）
				rs.beforeFirst();
				// 获取结果集中的所有的列的信息
				ResultSetMetaData rsmd = rs.getMetaData();
				// 获取结果集中列的个数
				int colCount = rsmd.getColumnCount();
				// 此处应该遍历打印一下列标题
				while (rs.next()) {
					// 创建存储当前行的bean对象
					T tBean = getInstance(clazz);
					// 遍历当前行的每列的信息
					for (int i = 1; i <= colCount; i++) {
						// 取出每一列的列名
						String strColName = rsmd.getColumnLabel(i);
						/*
						 * 注意：需要遵循约定规则：实体类的属性名和数据库的字段名名字要一样，且属性名要全部小写
						 */
						Object obj = rs.getObject(strColName);
						BeanUtils.setProperty(tBean, strColName.toLowerCase(), obj);	
					}
					// 将当前行的实体对象存入list中
					lst.add(tBean);
				}
			} catch (Exception e) {
				// 将查询结果集转换为List对象异常：
				System.out.println("将查询结果集转换为List对象异常：" + e.getMessage());
				e.printStackTrace();
			}
		}
		return lst;
	}
	public <T> List<T> queryBeanList(String strSql, Class<T> clazz) {
		// 返回值类型
		List<T> lst = null;
		try {
			// 获取数据库连接对象
			Connection conn = this.getConn();
			// (3) 获取statement执行器，执行sql语句
			Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
			// (4) 获取statement执行结果集resultset，并解析
			// 执行查询操作
			ResultSet rs = st.executeQuery(strSql);
			// 调用公用方法将，Resultset转换为list对象
			lst = convertResultSet2BeanList(rs, clazz);
			// 关闭资源
			rs.close();
			conn.close();
		} catch (SQLException e) {
			// 数据库操作类查询异常
			System.out.println("数据库操作类查询异常:" + e.getMessage());
			e.printStackTrace();
		}
		return lst;
	}
	
	/*public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		test03();
	}*/
	public static void main(String[] args) {
		updatetest();
	}
	static void updatetest() {
		String strSql = "UPDATE my_table_1 SET emp_id = 111,emp_name = '赵傻子', emp_salary = 1000 WHERE emp_id = 2";
		int i = getInstance(DBProvider.class).update(strSql);
		// 遍历结果集
		if (i > 0) {
			System.out.println("修改行记录成功");
		} else {
			System.out.println("修改行记录失败");
		}
	}
	static void deletetest() {
		String strSql = "DELETE my_table_1 WHERE emp_id = 25";
		int i = getInstance(DBProvider.class).delete(strSql);
		// 遍历结果集
		if (i > 0) {
			System.out.println("删除记录成功");
		} else {
			System.out.println("删除记录失败");
		}
	}
	/**
	 * 新增测试
	 */
	private static void test02_save2() {
		String name = "赵六";
		int salary = 9999;
		// sql语句
		String strSql = "INSERT INTO my_table_1(emp_name, emp_salary) VALUES(?,?)";
		// 调用新增操作
		// 准备传入参数数组
		List lstParas = new ArrayList();
		// 加入参数
		lstParas.add(name);		
		lstParas.add(salary);
		int i = getInstance(DBProvider.class).save(strSql,lstParas.toArray());
		// 遍历结果集
		if (i > 0) {
			System.out.println("插入成功");
		} else {
			System.out.println("插入失败");
		}
	}
	
	public void putdata() {
		String strSql = "select * from departments where department_id <= 60";
		// 将查询结果集转换为beanlist
		List<Departments> lst = queryBeanList(strSql, Departments.class);
		// 遍历结果集
		for (Departments dept : lst) {
			// System.out.println("部门：" + dept.getDepartment_name());
			System.out.println(dept.toString());
		}
	}
	
	/**
	 * 测试：DBProvider类的查询方法-返回list+bean的形式 —— 项目开发时使用的形式
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	private static void test03() throws InstantiationException, IllegalAccessException {
		// sql语句
		DBProvider.class.newInstance().putdata();
	}
	/**
	 * 新增数据
	 * 
	 * @param strSql
	 *            执行的sql语句
	 * @return 影响的记录行数
	 */
	public int save(String strSql) {
		// 返回值
		int i = 0;
		try {
			// 获取数据库连接对象
			Connection conn = this.getConn();
			// (3) 获取statement执行器，执行sql语句
			Statement st = conn.createStatement();
			// (4) 执行sql语句
			i = st.executeUpdate(strSql);
			// 关闭资源
			conn.close();
		} catch (Exception e) {
			// 数据库操作类新增异常
			System.out.println("数据库操作类新增数据异常:" + e.getMessage());
			e.printStackTrace();
		}
		return i;
	}

	/**
	 * 新增数据
	 * 
	 * @param strSql
	 *            执行的sql语句
	 * @param objParas
	 *            参数数组
	 * @return 影响的记录行数
	 */
	public int save(String strSql, Object[] objParas) {
		// 返回值
		int i = 0;
		try {
			// 获取数据库连接对象
			Connection conn = this.getConn();
			// (3) 获取PreparedStatement执行器，执行sql语句
			PreparedStatement pst = conn.prepareStatement(strSql);
			// 将参数数组给pst
			if (objParas != null) {
				for (int k = 1; k <= objParas.length; k++) {
					pst.setObject(k, objParas[k - 1]);
				}
			}
			// (4) 执行sql语句
			i = pst.executeUpdate();
			// 关闭资源
			conn.close();
		} catch (Exception e) {
			// 数据库操作类新增异常
			System.out.println("数据库操作类新增数据异常:" + e.getMessage());
			e.printStackTrace();
		}
		return i;
	}

	/**
	 * 修改数据
	 * 
	 * @param strSql执行的sql语句
	 * @return 影响的记录行数
	 */
	public int update(String strSql) {
		// 返回值
		int i = 0;
		try {
			// 获取数据库连接对象
			Connection conn = this.getConn();
			// (3) 获取statement执行器，执行sql语句
			Statement st = conn.createStatement();
			// (4) 执行sql语句
			i = st.executeUpdate(strSql);
			// 关闭资源
			conn.close();
		} catch (Exception e) {
			// 数据库操作类新增异常
			System.out.println("数据库操作类新增数据异常:" + e.getMessage());
			e.printStackTrace();
		}
		return i;
	}

	/**
	 * 删除数据
	 * 
	 * @param strSql执行的sql语句
	 * @return 影响的记录行数
	 */
	public int delete(String strSql) {
		// 返回值
		int i = 0;
		try {
			// 获取数据库连接对象
			Connection conn = this.getConn();
			// (3) 获取statement执行器，执行sql语句
			Statement st = conn.createStatement();
			// (4) 执行sql语句
			i = st.executeUpdate(strSql);
			// 关闭资源
			conn.close();
		} catch (Exception e) {
			// 数据库操作类新增异常
			System.out.println("数据库操作类删除数据异常:" + e.getMessage());
			e.printStackTrace();
		}
		return i;
	}
	/**
	 * 把数据映射为的JDBC数据类型转换常用java基本数据类型
	 * @param obj数据映射为的JDBC数据类型
	 * @param strDesDataType常用java基本数据类型
	 * @return 转换之后的数据类型
	 */
	private static Object convertJDBCDataType2JavaDataType(Object obj, String strDesDataType) {
		// 返回值类型
		Object obj_re = null;
		if (obj != null) {
			// 将不能映射为java基本类型的JDBC数据类型转为与之对应的java类型
			// 类型转换
			switch (strDesDataType.trim()) {
			case "java.lang.Long":
				obj_re = Long.parseLong(obj.toString());
				break;
			case "java.lang.Double":
				obj_re = Double.parseDouble(obj.toString());
				break;
			// ... 追加补充其他类型的转换

			// 不需要进行转换的数据类型直接返回即可
			default:
				obj_re = obj;
			}
		}
		// 返回值
		return obj_re;

	}

	/**
	 * 将查询结果集转何为List
	 * @param rs 查询结果集
	 * @return List结果
	 */

	/**
	 * 简单工厂模式：获取一个指定Class的实例对象
	 * 
	 * @param clazz
	 *            Class
	 * @return 实例对象
	 */
	public static <T> T getInstance(Class<T> clazz) {
		// 返回值
		T t = null;
		try {
			// 反射获取该Class的一个实例对象
			t = clazz.newInstance();
		} catch (Exception e) {
			// 获取实例对象异常
			System.out.println("获取实例对象异常:" + e.getMessage());
			e.printStackTrace();
		}
		return t;
	}
}

